package com.king;

import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class NamingGrpcClientProxyAgent {

    private static List<String> configLines = new ArrayList<>();

    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("加载自定义NacosAgent处理");
        // 读取配置文件
        if (agentArgs != null && !agentArgs.isEmpty()) {
            loadConfigFromFile(agentArgs);
        } else {
            // 尝试从当前jar包目录读取配置文件
            String jarFilePath = NamingGrpcClientProxyAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            String jarDir = jarFilePath.substring(0, jarFilePath.lastIndexOf('/') + 1);
            String configPath = jarDir + "nacosConfig.txt";
            if (configPath.startsWith("/")){
                configPath = configPath.replaceFirst("/", "");
            }
            loadConfigFromFile(configPath);
        }

        if (configLines == null || configLines.isEmpty()) {
            System.out.println("NacosAgent未发现配置文件nacosConfig.txt,取消Agent处理");
            return;
        }

        inst.addTransformer((loader, className, classBeingRedefined, protectionDomain, classfileBuffer) -> {
            // 解析配置
            StringBuilder configMapCode = new StringBuilder();
            configMapCode.append("   Object result = queryInstancesOfService($$); \n")
                    .append("   java.util.Map configMap = new java.util.HashMap(); \n");
            for (int i = 1; i < configLines.size(); i++) {
                String[] splitStr = configLines.get(i).split(" ");
                if (splitStr.length == 3){
                    configMapCode.append("   configMap.put(\"").append(splitStr[0]).append("\", \"").append(splitStr[1]).append(",").append(splitStr[2]).append("\"); \n");
                }
            }

            // 第一处
            String classNameTarget = "com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy";
            if (classNameTarget.replace(".", "/").equals(className)) {
                // 使用Javassist库对类进行转换
                javassist.ClassPool pool = javassist.ClassPool.getDefault();
                try {
                    javassist.CtClass cc = pool.get(classNameTarget);
                    javassist.CtMethod m = cc.getDeclaredMethod("queryInstancesOfService");

                    // 动态代码块
                    StringBuilder codeBlock = new StringBuilder();
                    // 加载自定义配置
                    codeBlock.append(configMapCode);
                    codeBlock.append("   if(result != null && result instanceof com.alibaba.nacos.api.naming.pojo.ServiceInfo) { \n" +
                            "          com.alibaba.nacos.api.naming.pojo.ServiceInfo instance = (com.alibaba.nacos.api.naming.pojo.ServiceInfo)result; \n" +
                            "          System.out.println(\"instance.getName():\" + instance.getName());" +
                            "          if (configMap.containsKey(instance.getName())){ \n" +
                            "            String configStr = configMap.get(instance.getName()); \n" +
                            "            String[] split = configStr.split(\",\"); \n" +
                            "            java.util.List hosts = instance.getHosts(); \n" +
                            "            int i = 1; \n" +
                            "            while (i <= hosts.size()) { \n" +
                            "             com.alibaba.nacos.api.naming.pojo.Instance item = hosts.get(i); \n" +
                            "             System.out.println(\"替换nacos实例节点IP\" + item.getIp() + \"为\" + split[0]);" +
                            "             item.setIp(split[0]); \n" +
                            "             item.setPort(Integer.parseInt(split[1])); \n" +
                            "             i = i + 1; \n" +
                            "            } \n" +
                            "          } \n" +
                            "       } \n" +
                            "       return result;");
                    String block = codeBlock.toString();
                    System.out.println("代理代码块：\n" + block);
                    m.insertBefore(block);
                    byte[] bytecode = cc.toBytecode();
                    cc.detach();
                    return bytecode;
                } catch (Exception e) {
                    System.out.println("加载异常");
                    e.printStackTrace();
                }
            }

            return classfileBuffer;
        });
    }

    private static void loadConfigFromFile(String filePath) {
        try {
            List<String> lines = Files.readAllLines(Paths.get(filePath));
            configLines.addAll(lines);
        } catch (IOException e) {
            System.err.println("Failed to read config file: " + filePath);
            e.printStackTrace();
        }
    }

    public static List<String> getConfigLines() {
        return configLines;
    }
}
